package com.github.cyf.nginx;

import com.github.cyf.entity.UploadResult;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;

/**
 * @author chenyifan
 * @create 2025-01-24 10:56
 */
@Data
@NoArgsConstructor
public class NginxFileServer {
    private String staticProxyDir;
    private String staticResourceUrl;

    public NginxFileServer(String staticProxyDir, String staticResourceUrl) {
        this.staticProxyDir = Paths.get(staticProxyDir).toString();
        this.staticResourceUrl = staticResourceUrl;
    }

    /**
     * 上传文件
     * @param multipartFile 上传的文件
     * @param group 分组
     * @return
     * @throws IOException
     */
    public UploadResult upload(MultipartFile multipartFile, String group) {
        if (!StringUtils.hasText(group)) {
            throw new NginxException("分组不能为空");
        }
        // 根据文件后缀名，在静态目录创建唯一的文件
        String extension = FilenameUtils.getExtension(multipartFile.getOriginalFilename());
        String newFileName = UUID.randomUUID() + "." + extension;
        String relativePath = normalizeRelativePath(group) + "/" + newFileName;
        File file = Paths.get(staticProxyDir, relativePath).toFile();
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        try {
            multipartFile.transferTo(file);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        UploadResult uploadResult = new UploadResult();
        uploadResult.setFileName(file.getName());
        uploadResult.setOriginalName(multipartFile.getOriginalFilename());
        uploadResult.setFileType(extension);
        uploadResult.setFilePath(file.getPath());
        uploadResult.setUrl(getStaticResourceUrl(relativePath));
        uploadResult.setRelativePath(relativePath);
        uploadResult.setFileSize(file.length());
        return uploadResult;
    }

    /**
     * 根据相对路径删除文件
     * @param relativePath 相对路径
     */
    public boolean deleteFile(String relativePath) {
        if (!StringUtils.hasText(relativePath)) {
            throw new NginxException("文件路径不能为空");
        }
        File file = new File(getAbsolutePath(relativePath));
        if (file.isDirectory()) {
            throw new NginxException("不能删除目录");
        }
        return file.delete();
    }

    /**
     * 获取相对路径
     * @param resourcePath 路径
     * @return
     */
    public String getRelativePathForStaticDir(String resourcePath) {
        if (!StringUtils.hasText(resourcePath)) {
            throw new NginxException("文件路径不能为空");
        }
        if (resourcePath.startsWith("http")) {
            // 判断是否是合法的url
            try {
                new URL(resourcePath);
                if (resourcePath.startsWith(staticResourceUrl)) {
                    String relativePath = resourcePath.replace(staticResourceUrl, "");
                    return normalizeRelativePath(relativePath);
                }
                throw new NginxException("文件地址" + resourcePath + "错误");
            } catch (Exception e) {
                throw new NginxException("文件地址" + resourcePath + "错误", e);
            }
        } else {
            // 文件绝对路径
            Path path = Paths.get(resourcePath);
            // 判断是否是静态代理目录下的文件
            if (path.isAbsolute() && path.startsWith(staticProxyDir)) {
                String relativePath = path.toString().replace(staticProxyDir, "");
                return normalizeRelativePath(relativePath);
            }
        }
        throw new NginxException("文件地址" + resourcePath + "错误");
    }

    /**
     * 根据相对路径获取文件的绝对路径
     * @param relativePath 相对路径
     * @return
     */
    public String getAbsolutePath(String relativePath) {
        if (!StringUtils.hasText(relativePath)) {
            throw new NginxException("文件路径不能为空");
        }
        return Paths.get(staticProxyDir, relativePath).toString();
    }

    /**
     * 获取文件的 URL
     * @param relativePath 相对路径
     * @return
     */
    public String getStaticResourceUrl(String relativePath) {
        if (!StringUtils.hasText(relativePath)) {
            throw new NginxException("文件路径不能为空");
        }
        return staticResourceUrl + relativePath;
    }


    /**
     * 序列化相对路径
     * @param path
     * @return
     */
    private static String normalizeRelativePath(String path) {
        if (!StringUtils.hasText(path)) {
            return null;
        }
        path = path.replaceAll("\\\\+", "/").replaceAll("/+", "/");
        if (!path.startsWith("/")) {
            path = "/" + path;
        }
        if (!path.equals("/") && path.endsWith("/")) {
            path = path.substring(0, path.length() - 1);
        }
        return path;
    }
}